;
(function($, $$) {

    $.fn.grid = function(options) {
        var self = this, args = Array.prototype.slice.call(arguments);
        args.push($$.Grid);
        var result = $$.createWidgetByJQuery.apply(self, args);
        if (result.jqObj !== undefined && options !== "widget") {
            return self;
        }
        return result;
    };

    $$.Grid = function(self, options) {
        if (!(this instanceof $$.Grid)) {
            return new $$.Grid(self, options);
        }
        var defaults = {

            gridClass : $$.defaultBorder + " uiCornerAll " + $$.defaultBoxShadow,

            titleBarClass : $$.defaultGradientBG,

            columnClass : "uiGrayGradientBG",

            trHoverClass : "uiTrHover",

            trOddClass : "uiTrOdd",

            trEvenClass : "uiTrEven",

            url : "grid.json",

            getData : null,

            resizable : true,

            minimize : true,

            closable : true,

            title : "表格",

            noTitleBar : false,

            titleIcon : null,

            hasControlButton : true,

            closeAnimate : "slideUp",

            openAnimate : "slideDown",

            minHeight : 300,

            maxHeight : 700,

            minWidth : 400,

            maxWidth : 1000,

            resultsPerPageOptions : [10, 20, 30],

            currentPage : 0,

            gridData : null,

            resultsPerPage : null,
            minStatusHeight : 0,

            originHeight : 0,

            originWidth : 0,

            originPosition : null,
            columnTableHeight : null,
            gettingMoreData : false,
            currentIndex : 0,
            total : 0,
            columnWidthList : null,
            tableWidth : 0,
            scrollLeft : 0,
            dragging : false,
            sortOrderList : null,
            controlButtonSetHTML : '<div class="uiGridButtonSet"><div class="uiUserBtn uiMinBtn"></div><div class="uiUserBtn uiCloseBtn"></div></div>',
            titleBarHTML : '<div class="uiTitleBar"><span class="uiTitle"></span></div>',
            contentHTML : '<div class="uiContent"></div>',
            resizeHTML :'<div class="uiResizable"></div>',
            contentHTML : '<div class="uiContent"></div>',
            buttonSetHTML : '<div class="uiGridButtonSet ui30GrayGradientBG"><div class="uiGridButtonContainer"><div class="uiGridButton uiSearchBtn"></div></div><div class="uiBtnSeparator"></div><div class="uiGridButtonContainer"><div class="uiGridButton uiGoToFirstBtn"></div></div><div class="uiGridButtonContainer"><div class="uiGridButton uiPrevBtn"></div></div><div class="uiBtnSeparator"></div><div class="uiGridButtonContainer"><div class="uiGridButton uiNextBtn"></div></div><div class="uiGridButtonContainer"><div class="uiGridButton uiGoToLastBtn"></div></div><div class="uiBtnSeparator"></div><div class="uiPageShowSelect"><select></select></div><div class="uiBtnSeparator"></div><div class="uiPageSetting"></div><div class="uiBtnSeparator"></div><div class="uiGridButtonContainer"><div class="uiGridButton uiRefreshBtn uiLoading"></div></div><div class="uiBtnSeparator"></div></div>',
            columnTableHTML : '<table class="uiColumnTable" cellspacing="0" cellpadding="0"><thead><tr></tr></thead></table>',
            dataTableHTML : '<div class="uiDataContainer"><table cellspacing="0" cellpadding="0"><tbody></tbody></table></div>',
            separatorHTML : '<div class="uiSeparator"></div>',
            sortHTML : '<span class="uiArrowDown uiSortIcon"></span>',

            beforeClose : null,
            close : null,
            beforeOpen : null,
            open : null,

            beforeMin : null,
            min : null,

            beforeResume : null,
            resume : null,
            dragStart : null,
            draging : null,
            dragStop : null,
            resizeStart : null,
            resizing : null,
            resizeStop : null

        };
        var opts = $.extend(defaults, options);
        $$.Grid.prototype.superClass.call(this, self, opts);
        this.init();
    };
    $$.inherit($$.Grid, $$.Widget, {

        init : function() {
            var gridObj = this;
            gridObj.createWidget();
            initGrid(gridObj.jqObj, gridObj.opts);
            return gridObj;
        }
    });

    function initGrid(self, opts) {
        $.ajax({
            url : opts.url,
            dataType : "json",
            success : function(data) {
                opts.gridJSON = data;
                setDataArray(opts.gridJSON.data, opts.gridJSON.total);
                opts.title = opts.title || self.attr("title");
                opts.sortOrderList = {};


                var controlButton = null;
                var tileBar, titleBarHeight = 0;
                if (opts.controlButton) {
                    controlButton = $(opts.controlButtonSetHTML);
                    if (!opts.minimize) {
                        controlButton.children(".uiMinBtn").hide();
                    }
                    if (!opts.closable) {
                        controlButton.children(".uiCloseBtn").hide();
                    }
                }

                if (opts.noTitleBar) {
                    self.addClass("uiGrid uiWidget " + opts.gridClass);
                }
                else {
                    tileBar = $(opts.titleBarHTML).addClass(opts.titleBarClass).append(controlButton).children(".uiTitle").html(opts.title).end();
                    if (opts.titleIcon !== null) {
                        tileBar.children(".uiTitle").prepend($('<span class="uiTitleIcon" />').addClass(opts.titleIcon));
                    }
                    self.addClass("uiGrid uiWidget " + opts.gridClass).prepend(tileBar);
                    titleBarHeight = tileBar.outerHeight(true);
                }

                var content = $(opts.contentHTML);
                opts.tableWidth = 0;
                var originColumnWidthList = opts.gridJSON.columnWidth;
                for (var i = 0, len = originColumnWidthList.length; i < len; i++) {
                    opts.tableWidth += originColumnWidthList[i];
                }
                var columnTable = $(opts.columnTableHTML).width(opts.tableWidth);
                var columnTr = columnTable.children("thead").addClass(opts.columnClass).children("tr");
                $.each(opts.gridJSON.column, function(i, value) {
                    columnTr.append($("<td>" + opts.sortHTML + value + "</td>").width(originColumnWidthList[i]));
                });
                content.append(columnTable);
                var dataObj = $(opts.dataTableHTML);
                var dataTable = dataObj.children("table").width(opts.tableWidth).children("tbody");
                content.append(dataObj);
                var buttonSet = $(opts.buttonSetHTML);
                var pageShowSelect = buttonSet.find(".uiPageShowSelect > select");
                var pageShowSelectOptionsList = "";
                opts.resultsPerPage = opts.resultsPerPageOptions[0];
                for (var i = 0, len = opts.resultsPerPageOptions.length; i < len; i++) {
                    pageShowSelectOptionsList += ("<option>" + opts.resultsPerPageOptions[i] + "</option>");
                }
                pageShowSelect.append(pageShowSelectOptionsList);
                var pageSetting = buttonSet.find(".uiPageSetting");
                pageSetting.html('<span>Page</span><input type="text" size="5" /><span>of ' + Math.ceil(opts.gridJSON.total / opts.resultsPerPage) + "</span>");
                buttonSet.find(".uiRefreshBtn").removeClass("uiLoading");
                self.append(content).append(buttonSet);
                var contentHeight = self.height() - titleBarHeight - buttonSet.outerHeight(true);
                content.height(contentHeight);
                opts.columnTableHeight = content.children(".uiColumnTable").outerHeight(true);
                content.children(".uiDataContainer").height(contentHeight - opts.columnTableHeight);
                if (opts.resizable) {
                    self.append(opts.resizeHTML);
                    if (self.css("position") === "static") {
                        self.css("position", "relative");
                    }
                }
                var separatorLeftValue = 0, separatorList = $();
                opts.columnWidthList = originColumnWidthList;
                $(">.uiContent >.uiColumnTable td", self).each(function(i) {
                    separatorLeftValue += $(this).outerWidth();
                    separatorList = separatorList.add($(opts.separatorHTML).css("left", separatorLeftValue - 1));
                });
                content.prepend(separatorList);
                setTable(self, opts, dataTable, 0);
                initEvent(self, opts);
            },
            error : function() {
                $$.destroy.call(self, true);
            }
        });
    }

    function initEvent(self, opts) {
        var posStr = self.css("position");
        var columnTable = $(">.uiContent>.uiColumnTable", self);
        $(">.uiContent>.uiDataContainer", self).bind("scroll.uiGrid", function(e) {
            var obj = $(this);
            var scrollLeftValue = obj.scrollLeft();
            var scrollTopValue = obj.scrollTop();
            if ($.prop !== undefined) {
                var maxScrollTopValue = obj.prop("scrollHeight") - obj.prop("clientHeight");
            }
            else {
                var maxScrollTopValue = obj.attr("scrollHeight") - obj.attr("clientHeight");
            }
            if (opts.scrollLeft !== scrollLeftValue) {
                columnTable.css("marginLeft", -scrollLeftValue);
                opts.scrollLeft = scrollLeftValue;
                setSeparatorPos(self, opts);
            }
            if (maxScrollTopValue === scrollTopValue) {
                var dataTable = $(">.uiContent >.uiDataContainer >table >tbody", self);
                setTable(self, opts, dataTable, opts.currentIndex + opts.resultsPerPage);
            }
        })
            .bind({
                "mouseover.uiGrid" : function(e) {
                    if (opts.dragging) {
                        return;
                    }
                    var target = $(e.target);
                    if (target.hasClass("uiDataContainer")) {
                        return;
                    }
                    var trObj = target.parentsUntil("tbody").addClass(opts.trHoverClass);
                },
                "mouseout.uiGrid" : function(e) {
                    var target = $(e.target);
                    var trObj = target.parentsUntil("tbody").removeClass(opts.trHoverClass);
                }
            });
        self.find("> .uiTitleBar > .uiGridButtonSet > .uiUserBtn").bind("click.uiGrid", function(e) {
            if (opts.disabled) {
                return false;
            }
            var obj = $(this);
            if (obj.hasClass("uiMinBtn")) {
                $$.min.call(self, obj, e);
                return false;
            }
            else
            if (obj.hasClass("uiResumeBtn")) {
                $$.resume.call(self, obj, e);
                return false;
            }
            else
            if (obj.hasClass("uiCloseBtn")) {
                $$.close.call(self, obj, e);
                return false;
            }
        });
        var originPositon;
        $(">.uiContent >.uiSeparator", self).draggable({
            getUserMask : function() {
                return $(this).addClass("uiSeparatorShow");
            },
            event : {
                start : function() {
                    originPositon = $(this).position();
                },
                doing : function(mask, position) {
                    opts.dragging = true;
                    $(this).css("left", position.left);
                    return false;
                },
                stop : function(mask, position) {
                    opts.dragging = false;
                    $(this).removeClass("uiSeparatorShow");
                    var index = mask.prevAll(".uiSeparator").length;
                    var offsetLength = position.left - originPositon.left;
                    var tableObj = $(">.uiContent >.uiColumnTable", self);
                    var tdObj = $(">thead >tr >td", tableObj).eq(index);
                    var columnNewWidth = opts.columnWidthList[index] + offsetLength;
                    if (columnNewWidth < 0) {
                        mask.css(originPositon);
                        return false;
                    }
                    opts.tableWidth += offsetLength;
                    opts.columnWidthList[index] = columnNewWidth;

                    tableObj.width(opts.tableWidth);
                    tdObj.width(opts.columnWidthList[index]);

                    tableObj = $(">.uiContent >.uiDataContainer >table", self);
                    tdObj = $(">tbody >tr >td", tableObj).eq(index);

                    tableObj.width(opts.tableWidth);
                    tdObj.width(opts.columnWidthList[index]);

                    setSeparatorPos(self, opts);
                    return false;
                }
            }
        });
        $(">.uiContent >.uiColumnTable td", self).bind("mouseenter.uiGrid mouseleave.uiGrid", function(e) {
            var value = "hidden";
            if (e.type === "mouseenter") {
                value = "visible";
            }
            $(this).children(".uiSortIcon").css("visibility", value);
        });
        $(">.uiContent >.uiColumnTable", self).bind("click.uiGrid", function(e) {
            var target = $(e.target);
            if (target.hasClass("uiSortIcon")) {
                target = target.parent();
            }
            var index = target.index();
            var sortIcon = target.children(".uiSortIcon");
            if (sortIcon.length === 0) {
                target.prepend(opts.sortHTML);
                sortIcon = target.children(".uiSortIcon");
            }
            if (sortIcon.hasClass("uiArrowUp")) {
                sortIcon.removeClass("uiArrowUp");
                opts.sortOrderList[index] = "des";
            }
            else {
                sortIcon.addClass("uiArrowUp");
                opts.sortOrderList[index] = "asc";
            }
            var btnObj = $(">.uiGridButtonSet .uiRefreshBtn", self).addClass("uiLoading");
            setTimeout(function() {
                sortTable($(">.uiContent >.uiDataContainer >table >tbody", self), opts, index);
                btnObj.removeClass("uiLoading");
            }, 30);
        });
        $(">.uiGridButtonSet", self).bind("click.uiGrid", function(e) {
            var obj = $(this);
            var target = $(e.target);
            var dataTable = $(">.uiContent >.uiDataContainer >table >tbody", self);
            $(">.uiContent>.uiDataContainer", self).scrollLeft(0).scrollTop(0);
            var page = parseInt(obj.find(">.uiPageSetting >input").val()) - 1;
            if (target.hasClass("uiRefreshBtn")) {
                var index = page * opts.resultsPerPage;
                setTable(self, opts, dataTable, index, true);
            }
            else
            if (target.hasClass("uiGoToFirstBtn")) {
                setTable(self, opts, dataTable, 0, true);
            }
            else
            if (target.hasClass("uiPrevBtn")) {
                var index = (page - 1) * opts.resultsPerPage;
                setTable(self, opts, dataTable, index, true);
            }
            else
            if (target.hasClass("uiNextBtn")) {
                var index = (page + 1) * opts.resultsPerPage;
                setTable(self, opts, dataTable, opts.currentIndex + opts.resultsPerPage, true);
            }
            else
            if (target.hasClass("uiGoToLastBtn")) {
                setTable(self, opts, dataTable, opts.gridJSON.total - opts.resultsPerPage, true);
            }
        })
            .find(">.uiPageShowSelect >select").bind("change.uiGrid", function(e) {
                opts.resultsPerPage = parseInt($(this).val());
                var totalPage = Math.ceil(opts.gridJSON.total / opts.resultsPerPage);
                var textValue = "of " + totalPage;
                $(this).parent().siblings(".uiPageSetting").children("span:last").text(textValue);
                var dataTable = $(">.uiContent >.uiDataContainer >table >tbody", self);
                setTable(self, opts, dataTable, 0, true);
            });
        if (opts.resizable) {
            var resizeStopFunc = function(mask, width, height) {
                if (opts.disabled) {
                    return false;
                }
                if ($.isFunction(opts.resizeStop)) {
                    if (opts.resizeStop.call(self) === false) {
                        return false;
                    }
                }
                height = Math.min(Math.max(opts.minHeight, height), opts.maxHeight);
                width = Math.min(Math.max(opts.minWidth, width), opts.maxWidth);
                var otherItemHeightTotal = 0, content = self.width(width).height(height).children(".uiContent");
                self.children().each(function() {
                    var obj = $(this);
                    if (!obj.hasClass("uiContent") && !obj.hasClass("uiResizable")) {
                        otherItemHeightTotal += $(this).outerHeight(true);
                    }
                });
                var outerOffset = content.outerHeight(true) - content.height();
                var contentHeight = height - otherItemHeightTotal - outerOffset;
                content.height(contentHeight).children(".uiDataContainer").height(contentHeight - opts.columnTableHeight);
            };
            self.resizable({
                event : {start : opts.resizeStart, doing : opts.resizing,  stop : resizeStopFunc},
                minHeight : opts.minHeight,
                maxHeight : opts.maxHeight,
                minWidth : opts.minWidth,
                maxWidth : opts.maxWidth
            });
        }
    }

    function setTable(self, opts, dataTable, index, clearData) {
        if (opts.gettingMoreData) {
            return;
        }
        if (index < 0) {
            index = 0;
        }
        else
        if (index > opts.gridJSON.total - 1) {
            return;
        }
        var offsetIndex, columnWidthList = opts.columnWidthList;
        var data = opts.gridJSON.data;
        var getIndex = opts.currentIndex = index;
        if (opts.currentIndex + opts.resultsPerPage > opts.gridJSON.total - 1) {
            getIndex = opts.gridJSON.total - opts.resultsPerPage - 1;
        }
        if (data[getIndex + opts.resultsPerPage] === null) {
            if ($.isFunction(opts.getData)) {
                var btnObj = $(">.uiGridButtonSet .uiRefreshBtn", self).addClass("uiLoading");
                opts.gettingMoreData = true;
                opts.getData({currentIndex : opts.currentIndex}, function(newData) {
                    btnObj.removeClass("uiLoading");
                    replaceDataArray(data, newData, opts.currentIndex);
                    var dataTable = $(">.uiContent >.uiDataContainer >table >tbody", self);
                    opts.gettingMoreData = false;
                    setTable(self, opts, dataTable, opts.currentIndex, clearData);
                });
            }
            return;
        }
        if (clearData === true) {
            dataTable.empty();
        }
        var total = Math.min(opts.currentIndex + opts.resultsPerPage, opts.gridJSON.total);
        for (var i = opts.currentIndex; i < total; i++) {
            var trObj = $("<tr></tr>");
            if (i % 2 === 1) {
                trObj.addClass(opts.trEvenClass);
            }
            else {
                trObj.addClass(opts.trOddClass);
            }
            var value = data[i];
            if (value === null) {
                break;
            }
            for (var j = 0, lenColumn = value.length; j < lenColumn; j++) {
                var tdObj = $("<td>" + value[j] + "</td>");
                if (i === 0 || (clearData === true && i === opts.currentIndex)) {
                    tdObj.width(columnWidthList[j]);
                }
                trObj.append(tdObj);
            }
            dataTable.append(trObj);
        }
        opts.currentPage = Math.ceil((opts.currentIndex + opts.resultsPerPage) / opts.resultsPerPage);
        $(">.uiGridButtonSet >.uiPageSetting > input", self).val(opts.currentPage);
    }

    function setSeparatorPos(self, opts) {
        var columnWidthList = opts.columnWidthList;
        var leftOffset = 0;
        var separatorList = $("> .uiContent > .uiSeparator", self);
        var separatorLeftValue = 0;
        $(">.uiContent >.uiColumnTable td", self).each(function(i) {
            separatorLeftValue += $(this).outerWidth();
            separatorList.eq(i).css("left", separatorLeftValue - 1 - opts.scrollLeft);
        });
    }

    function setDataArray(data, total) {
        var dataLength = data.length;
        for (var i = dataLength; i < total; i++) {
            data.push(null);
        }
    }

    function replaceDataArray(data, newData, replaceIndex) {
        var total = replaceIndex + newData.length;
        var index = 0;
        for (var i = replaceIndex; i < total; i++) {
            if (data[i] === undefined) {
                break;
            }
            data[i] = newData[index++];
        }
    }

    function sortTable(table, opts, index) {

        var itemList = table.children();
        var firstTdList = itemList.eq(0).children();
        var columnTotal = firstTdList.length;
        var tmpArr = $.makeArray(itemList);
        var sortOrderList = opts.sortOrderList;
        var columnWidthList = opts.columnWidthList;
        var sortOrder = sortOrderList[index] || "asc";

        itemList.each(function() {
            var obj = $(this);
            var key = obj.children().eq(index).html();
            this.gridSortOrderKey = key;
            obj.removeClass();
        });
        tmpArr.sort(compare);
        $(tmpArr[0]).children().each(function(n) {
            $(this).width(columnWidthList[n]);
        });
        for (var i = 0, len = tmpArr.length; i < len; i++) {
            delete tmpArr[i].gridSortOrderKey;
            if (i % 2 === 0) {
                $(tmpArr[i]).addClass(opts.trOddClass);
            }
            else {
                $(tmpArr[i]).addClass(opts.trEvenClass);
            }
        }
        table.append(tmpArr);
        function compare(item1, item2) {
            var value1 = item1.gridSortOrderKey;
            var value2 = item2.gridSortOrderKey;
            var testReg = /\d+/;
            var result = testReg.exec(value1);
            if (result !== null) {
                value1 = parseInt(value1);
                value2 = parseInt(value2);
            }
            if (value1 > value2) {
                if (sortOrder === "asc") {
                    return 1;
                }
                return -1;
            }
            else
            if (value1 < value2) {
                if (sortOrder === "asc") {
                    return -1;
                }
                return 1;
            }
            return 0;
        }
    }
})(jQuery, BASE);